home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / mref.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  25KB  |  1,076 lines

  1. /* mref - MINIX cross referencer    Author: Andy Tanenbaum */
  2.  
  3. /* Mref is intended for producing listings and cross reference maps of
  4.  * MINIX.  The default is to produce three outputs:
  5.  *
  6.  *    on stdout:    numbered listing of all the files given as args
  7.  *    on symbol.out:    list of all "global" symbols and their definition line
  8.  *    on xref.out:    cross reference map of all references to global symbols
  9.  *
  10.  * For this program, a global symbol is one that is defined as PUBLIC, PRIVATE,
  11.  * EXTERN, #define, or SYMBOL.  The latter is provided to allow users to force
  12.  * symbols x, y, and z to "global" status but simply making up a file with
  13.  *
  14.  *    SYMBOL x
  15.  *    SYMBOL y
  16.  *    SYMBOL z
  17.  *
  18.  * The numbering is consecutive across files, i.e., the second file begins
  19.  * where the first one left off, except that each file begins at the top of
  20.  * a new page, and the line number is rounded upward to the next page.
  21.  * The three types of output can each be suppressed, using the -l, -d, and -x
  22.  * flags, respectively.  Line numbering between procedures may be optionally
  23.  * suppressed with -s, as in the MINIX book.  Page length and numbering can be
  24.  * user controlled with flags.
  25.  *
  26.  * Normally output is designed for a dumb line printer, but the -t flag causes
  27.  * the output to be enhanced with macros and font control so it can be fed to
  28.  * troff (or nroff).  If troff form, the symbol table is printed in three
  29.  * columns, the first page being shorter to allow for the chapter opening.
  30.  *
  31.  * Flags:
  32.  *    -#    Number of lines to print per page, default = 50
  33.  *    -d    Don't produce definition file (symbol table)
  34.  *    -l    Don't produce listing
  35.  *    -m    Multiple reference on one line only are cited once
  36.  *    -p n    Set initial page number to n
  37.  *    -t    Generate troff macro call before each page
  38.  *    -s    Suppress line numbering between procedures
  39.  *    -x    Don't produce the cross reference map
  40.  *
  41.  * Examples:
  42.  *    mref -60 *.c        # print 60 lines per page (default is 50)
  43.  *    mref -t -p 50 *.c    # first page is 50; generate .Ep and .Op macros
  44.  *    mref -l -d *.h *.c    # no listing or symbols, just cross ref map
  45.  */
  46.  
  47. #include <sys/types.h>
  48. #include <ctype.h>
  49. #include <fcntl.h>
  50. #include <stdio.h>
  51.  
  52. #define LINE_SIZE     512
  53. #define PHYS_PAGE      66    /* physical page length */
  54. #define DEF_LEN        50    /* default # lines/page */
  55. #define SYM_SIZE       13    /* symbols are truncated to this size */
  56. #define HDR_SIZE        5    /* number of lines in the default header */
  57. #define NSYMS        2000    /* size of the symbol table */
  58. #define NTOKENS       100    /* maximum number of tokens per line */
  59. #define MAX_VALUES    100    /* maximum times a name can be declared */
  60. #define MAX_PER_LINE    9    /* number of cross refs to print per line */
  61. #define NCOLS           3    /* number of columns for troffed symbol.out */
  62.  
  63. #define SYM_FILE "symbol.out"    /* place to write the symbol table */
  64. #define XREF_FILE "xref.out"    /* place to write cross ref map */
  65. #define TMP_FILE  "xref.tmp"    /* temporary xref file for gathering refs */
  66. #define SORTED_FILE "xref.sort"    /* temporary xref file for sorting */
  67.  
  68. #define DEF             1    /* this line contains #define */
  69. #define EXT             2    /* this line contains EXTERN  */
  70. #define PRIV            3    /* this line contains PRIVATE */
  71. #define PUB             4    /* this line contains PUBLIC  */
  72. #define SYM             5    /* this line contains SYMBOL  */
  73.  
  74. int listing = 1;        /* 1 = output listing;        0: don't */
  75. int xref = 1;            /* 1 = output cross ref map;    0: don't */
  76. int definitions = 1;        /* 1 = output definitions;    0: don't */
  77. int sflag = 0;            /* 1 = number all lines;    0: most  */
  78. int tflag = 0;            /* 1 = troff output;        0: flat  */
  79. int mflag = 0;            /* 1 = max one ref/line        0: many  */
  80.  
  81. int page_len = DEF_LEN;        /* # lines to print per page */
  82. int phys_page = PHYS_PAGE;    /* total page size: top hdr+text+bottom hdr */
  83. int cur_line;            /* current line number */
  84. int cur_page = 1;        /* current page number */
  85. int ntokens;            /* number of tokens in the token[] array */
  86. int suppressing;        /* don't print numbers between procedures */
  87. int hunting;            /* set when hunting for end of declaration */
  88. int comment;            /* set when scanning a comment */
  89. int xcount;            /* number of references so far to this sym */
  90. int prev_ref;            /* previous reference printed */
  91. int stride;            /* length of first symbol table page */
  92. int stride2;            /* length of second symbol table page */
  93.  
  94. char *prog_name;        /* argv[0] */
  95. char line_buf[LINE_SIZE];    /* buffer for 1 line */
  96. char b[LINE_SIZE];        /* processed line goes here */
  97. char *token[NTOKENS];        /* array of pointers to tokens */
  98.  
  99. /* Symbol table.  If a symbol is defined multiple times, it will get as many
  100.  * entries in the symbol table as there are definitions.
  101.  */
  102. struct symtab {
  103.   char sym_name[SYM_SIZE + 1];    /* symbol, followed by at least one '\0' */
  104.   char sym_type;        /* PUB, PRIV, EXT, SYM, or DEF */
  105.   int sym_val;            /* line number on which symbol occurs */
  106. } symtab[NSYMS];
  107.  
  108. char *ppmap[] = {"", "#define", "EXTERN ", "PRIVATE", "PUBLIC ", "SYMBOL "};
  109. char *ppmap2[] = {"", "#def", "EXTN", "PRIV", "PUBL", "SYMB"};
  110. char spaces[] = "                ";
  111.  
  112. char *xref_text[] = {
  113.   ".nf\n",
  114.   ".tr _\\(ru\n",
  115.   ".ta 1.25i 2iR 2.45iR 2.9iR 3.35iR 3.8iR 4.25iR 4.7iR 5.15iR 5.6iR 6.05iR\n",
  116.   (char *) 0
  117. };
  118.  
  119. char *list_text[] = {
  120.   ".po .5i\n",
  121.   ".lg 0\n",
  122.   ".nf\n",
  123.   ".ec `\n",
  124.   ".ps 10\n",
  125.   ".vs 12p\n",
  126.   "`f(lb\n",
  127.   ".nr T `w'0'\n",
  128.   ".ta 8u*`nTu 16u*`nTu 24u*`nTu 32u*`nTu 40u*`nTu 48u*`nTu 56u*`nTu 64u*`nTu 72u*`nTu 80u*`nTu\n",
  129.   ".de Op \n",
  130.   ".bp ``$1\n",
  131.   ".sp 0.5i\n",
  132.   ".tl '``fR``s10MINIX SOURCE CODE``s0'``s11File: ``$2``s0``fP'``fB``s12``n%%``s0``fP'\n",
  133.   ".sp 1\n",
  134.   "``f(lb\n",
  135.   "..\n",
  136.   ".de Ep \n",
  137.   ".bp ``$1\n",
  138.   ".sp 0.5i\n",
  139.   ".tl '``fB``s12``n%%``s0``fP``fR'``s11File: ``$2'``s0``s10MINIX SOURCE CODE``s0``fP'\n",
  140.   ".sp 1\n",
  141.   "``f(lb\n",
  142.   "..\n",
  143.   (char *) 0
  144. };
  145.  
  146. char *sym_text[] = {
  147.   ".nf\n",
  148.   ".tr _\\(ru\n",
  149.   ".ta 1.6iR 2.0i 3.6iR 4.0i 5.6iR\n",
  150.   (char *) 0
  151. };
  152.  
  153.  
  154.  
  155. FILE *sym;            /* for symbol table file */
  156. FILE *xr;            /* for cross reference file */
  157. FILE *tmp;            /* for collecting cross references */
  158. FILE *sortf;            /* for sorting cross refernces */
  159.  
  160. main(argc, argv)
  161. int argc;
  162. char *argv[];
  163. {
  164.  
  165.   int i, j;
  166.   char *p;
  167.  
  168.   prog_name = argv[0];
  169.  
  170.   /* Process the command line. */
  171.   if (argc < 2) usage();
  172.  
  173.   for (i = 1; i < argc; i++) {
  174.     p = argv[i];
  175.     if (*p != '-') break;
  176.     p++;
  177.     i += eat_flag(argv, i);
  178.   }
  179.   stride = page_len / 2;    /* allow for chapter opening */
  180.   stride2 = page_len;
  181.  
  182.  
  183.   /* Create the output files. */
  184.   make_files();
  185.  
  186.   /* Read all the files. Make the listing and extract the symbols. */
  187.   for (j = i; j < argc; j++) process(argv[j]);
  188.  
  189.   if (xref) {
  190.     /* Read all the files again and generate the cross
  191.      * refererence data. */
  192.     cur_line = 0;
  193.     for (j = i; j < argc; j++) gen_xref(argv[j]);
  194.  
  195.     /* Go get the cross reference data and print it. */
  196.     collect_xref();
  197.   }
  198.  
  199.   /* Print the symbol table. */
  200.   if (definitions) print_sym();
  201.  
  202.   exit(0);
  203. }
  204.  
  205.  
  206. int eat_flag(argv, i)
  207. char *argv[];            /* argument array */
  208. int i;                /* process argv[i] */
  209. {
  210.   char *p;
  211.   int r = 0;
  212.  
  213.   p = argv[i];
  214.   p++;
  215.   if (*p >= '0' && *p <= '9') {
  216.     page_len = atoi(p);    /* e.g. numb -60 file */
  217.     return(r);
  218.   }
  219.   while (1) {
  220.     /* Flag may be something like -dls. */
  221.     switch (*p) {
  222.         case 'd':    definitions = 0;    break;
  223.         case 'l':    listing = 0;    break;
  224.         case 'x':    xref = 0;    break;
  225.         case 'm':    mflag = 1;    break;
  226.         case 's':    sflag = 1;    break;
  227.         case 't':    tflag = 1;    break;
  228.  
  229.         case 'p':
  230.         cur_page = atoi(argv[i + 1]);
  231.         i++;
  232.         r = 1;
  233.         break;
  234.  
  235.         default:    usage();
  236.     }
  237.     p++;
  238.     if (*p == 0) return(r);
  239.   }
  240. }
  241.  
  242.  
  243. make_files()
  244. {
  245. /* Create output files. */
  246.  
  247.   int fd;
  248.  
  249.   if (tflag && listing) output_macros(stdout, list_text);
  250.  
  251.   if (definitions) {
  252.     if ((fd = creat(SYM_FILE, 0666)) < 0) {
  253.         fprintf(stderr, "%s: cannot create %s\n", prog_name, SYM_FILE);
  254.         exit(2);
  255.     }
  256.     close(fd);
  257.     sym = fopen(SYM_FILE, "w");
  258.     if (sym == NULL) {
  259.         fprintf(stderr, 
  260.                "%s: cannot open %s for output\n", prog_name, SYM_FILE);
  261.         exit(2);
  262.     }
  263.     if (tflag) output_macros(sym, sym_text);
  264.   }
  265.   if (xref) {
  266.     if ((fd = creat(XREF_FILE, 0666)) < 0) {
  267.         fprintf(stderr,"%s: cannot create %s\n", prog_name, XREF_FILE);
  268.         exit(2);
  269.     }
  270.     close(fd);
  271.     xr = fopen(XREF_FILE, "w");